package net.pierrerenaudin.blobbyvolley.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;

public class GameController {

	private int refreshTime = 12; //ms
	private boolean isGameLoaded = false;

	private Player rightPlayer;
	private Player leftPlayer;
	private Ball ball;

	private UIManager uiManager;
	
	private PhysicEngine physicEngine;
	private RenderManager renderManager;
	private SoundManager soundManager;
	private KeyboardManager keyboardManager;

	private Player servingPlayer;
	private Player winPlayer;

	// Timer
	final Timer gameTimer = new Timer() {
		@Override
		public void run() {
			winPlayer = update();
			if(winPlayer != null){
				uiManager.startWin(winPlayer);
			}
		}
	};
	
	public GameController(UIManager uiManager){
		this.uiManager = uiManager;
		
		leftPlayer = new Player(Player.LEFT_PLAYER);
		rightPlayer = new Player(Player.RIGHT_PLAYER);
		ball = new Ball();

		// Init game values
		keyboardManager = new KeyboardManager();
		physicEngine = new PhysicEngine(this);

		physicEngine.cleanPhysic();
		resetRuleVars();
		physicEngine.resetPlayer();
		physicEngine.reset(leftPlayer);

		// Game Manager
		renderManager = new RenderManager(this);
		soundManager = new SoundManager();
	}

	public void start(){
		gameTimer.scheduleRepeating(refreshTime);
	}
	
	public void pause(){
		gameTimer.cancel();
	}
	

	public Player update(){
		physicEngine.update();
		renderManager.drawGame();

		// Protection of multiple hit counts when the ball is squeezed
		if (0 == leftPlayer.squish)
		{
			if (ball.hitPlayer(leftPlayer))
			{
				soundManager.playTouch();
				leftPlayer.hitCount++;
				rightPlayer.hitCount = 0;
				leftPlayer.squish = 1;
			}
		}
		else
		{
			leftPlayer.squish += 1;
			if(leftPlayer.squish > 9)
			{		
				leftPlayer.squish = 0;
			}
		}

		if(0 == rightPlayer.squish)
		{
			if(ball.hitPlayer(rightPlayer))
			{
				soundManager.playTouch();
				rightPlayer.hitCount++;
				leftPlayer.hitCount = 0;
				rightPlayer.squish = 1;
			}
		}
		else
		{
			rightPlayer.squish += 1;
			if(rightPlayer.squish > 9)
			{
				rightPlayer.squish = 0;
			}
		}

		if (physicEngine.ballHitLeftGround() || leftPlayer.hitCount > 3)
		{
			soundManager.playWhistle();
			if (leftPlayer.hitCount > 3)
			{
				physicEngine.dampBall();
			}
			if (rightPlayer.isServing())
			{
				rightPlayer.score++;
			}
			rightPlayer.setServing(true);
			leftPlayer.setServing(false);
			servingPlayer = rightPlayer;

			physicEngine.setBallValidity(false);
			ball.down = true;
			rightPlayer.hitCount = 0;
			leftPlayer.hitCount = 0;
			rightPlayer.squish = 0;
			leftPlayer.squish = 0;
		}

		if (physicEngine.ballHitRightGround() || rightPlayer.hitCount > 3)
		{
			soundManager.playWhistle();
			if(rightPlayer.hitCount > 3)
			{
				physicEngine.dampBall();
			}
			if (leftPlayer.isServing())
			{
				leftPlayer.score++;
			}
			servingPlayer = leftPlayer;
			leftPlayer.setServing(true);
			rightPlayer.setServing(false);

			physicEngine.setBallValidity(false);
			ball.down = true;
			rightPlayer.hitCount = 0;
			leftPlayer.hitCount = 0;
			rightPlayer.squish = 0;
			leftPlayer.squish = 0;
		}

		if (physicEngine.roundFinished())
		{
			ball.down = false;
			physicEngine.reset(servingPlayer);
		}

		if (leftPlayer.score >= 15 && leftPlayer.score >= rightPlayer.score + 2)
		{
			winPlayer = leftPlayer;
		}	
		if (rightPlayer.score >= 15 && rightPlayer.score >= leftPlayer.score + 2)
		{
			winPlayer = rightPlayer;
		}

		return winPlayer;
	}

	public void resetRuleVars(){
		leftPlayer.score = 0;
		rightPlayer.score = 0;

		leftPlayer.squish = 0;
		rightPlayer.squish = 0;

		leftPlayer.hitCount = 0;
		rightPlayer.hitCount = 0;

		servingPlayer = null;

		leftPlayer.state = 0;
		rightPlayer.state = 0;

		leftPlayer.animationSpeed = 0;
		rightPlayer.animationSpeed = 0;
	}

	public Player getRightPlayer() {
		return rightPlayer;
	}

	public void setRightPlayer(Player rightPlayer) {
		this.rightPlayer = rightPlayer;
	}

	public Player getLeftPlayer() {
		return leftPlayer;
	}

	public void setLeftPlayer(Player leftPlayer) {
		this.leftPlayer = leftPlayer;
	}

	public void setBall(Ball ball) {
		this.ball = ball;
	}

	public Ball getBall() {
		return ball;
	}

	public RenderManager getRenderManager() {
		return renderManager;
	}

	public SoundManager getSoundManager() {
		return soundManager;
	}

	public void setKeyboardManager(KeyboardManager keyboardManager) {
		this.keyboardManager = keyboardManager;
	}

	public KeyboardManager getKeyboardManager() {
		return keyboardManager;
	}

	public void setGameLoaded(boolean isGameLoaded) {
		this.isGameLoaded = isGameLoaded;
	}

	public boolean isGameLoaded() {
		return isGameLoaded;
	}
	
	public Canvas getGameCanvas(){
		return renderManager.getCanvas();
	}

}
